/*
A stack is a version of a list with zero or more elements. In a stack data structure, all insertions and deletions of elements are made at one end,called the top of the stack. If a stack is empty, a removal operations is illegal. If a stack is full, then an add operation is illegal.Define a class template Stack that represents the concept of stacks, and the interface is customized. 
//定义一个表示“栈”概念的类模板，接口自定
*/
#include <iostream>
using namespace std;

template <class T,int MAX_CAPACITY>
class Stack{
public:
    Stack();
    ~Stack();
    bool isEmpty(){return size<=0;};
    bool isFull(){return size>=MAX_CAPACITY;};
    void push(const T& t);
    T pop();
private:
    T* arr;
    int size;
};

template <class T,int MAX_CAPACITY>
Stack<T,MAX_CAPACITY>::Stack(){
    arr=new T[MAX_CAPACITY];
    size=0;
}
template <class T,int MAX_CAPACITY>
Stack<T,MAX_CAPACITY>::~Stack(){
    if(arr)delete[] arr;
}
template <class T,int MAX_CAPACITY>
void Stack<T,MAX_CAPACITY>::push(const T& t){
    if(isFull()){
        cerr<<"Stack is Full!"<<endl;
        return;
        }
    arr[size++]=t;
    cout<<"PUSH OK!"<<endl;
}
template <class T,int MAX_CAPACITY>
T Stack<T,MAX_CAPACITY>::pop(){
    if(isEmpty()){
        cerr<<"Stack is Empty!"<<endl;
        return NULL;
    }
    return arr[--size];
}

//用于测试的class  A
class A
{
public:
    int data;
    A(int i=0):data(i){};
};

int main(int argc, char const *argv[])
{
    Stack<int,2> si;
    cout<<"isEmpty:"<<si.isEmpty()<<endl;
    si.push(1);
    si.push(2);
    si.push(3);//Stack is Full!
    cout<<"isFull:"<<si.isFull()<<endl;
    cout<<"POP:"<<si.pop()<<endl;
    cout<<"POP:"<<si.pop()<<endl;
    cout<<"POP:"<<si.pop()<<endl;//Stack is Empty!
    cout<<"isEmpty:"<<si.isEmpty()<<endl;

    cout<<"----------------"<<endl;
    Stack<A,2> sa;
    cout<<"isEmpty:"<<sa.isEmpty()<<endl;
    sa.push(A(1));
    sa.push(A(2));
    cout<<"isFull:"<<sa.isFull()<<endl;
    cout<<"POP:"<<sa.pop().data<<endl;
    cout<<"POP:"<<sa.pop().data<<endl;
    cout<<"isEmpty:"<<sa.isEmpty()<<endl;
    return 0;
}
